package registry

import (
	"errors"
	"sync"

	"gitee.com/yuebanlaosiji/gocelery/pkg/types"
)

var (
	// ErrTaskNotFound is returned when a task is not found in the registry
	ErrTaskNotFound = errors.New("task not found")

	// ErrTaskAlreadyRegistered is returned when a task is already registered
	ErrTaskAlreadyRegistered = errors.New("task already registered")

	// ErrNilHandler is returned when trying to register a nil handler
	ErrNilHandler = errors.New("cannot register nil handler")
)

// MemoryRegistry implements the Registry interface using an in-memory map
type MemoryRegistry struct {
	tasks map[string]types.TaskFunc
	mu    sync.RWMutex
}

// NewMemoryRegistry creates a new in-memory task registry
func NewMemoryRegistry() *MemoryRegistry {
	return &MemoryRegistry{
		tasks: make(map[string]types.TaskFunc),
	}
}

// Register registers a task handler
func (mr *MemoryRegistry) Register(name string, handler types.TaskFunc) error {
	if handler == nil {
		return ErrNilHandler
	}

	mr.mu.Lock()
	defer mr.mu.Unlock()

	// Check if task already exists
	if _, exists := mr.tasks[name]; exists {
		return ErrTaskAlreadyRegistered
	}

	mr.tasks[name] = handler
	return nil
}

// GetTask gets a task handler by name
func (mr *MemoryRegistry) GetTask(name string) (types.TaskFunc, error) {
	mr.mu.RLock()
	defer mr.mu.RUnlock()

	handler, exists := mr.tasks[name]
	if !exists {
		return nil, ErrTaskNotFound
	}

	return handler, nil
}

// HasTask checks if a task exists
func (mr *MemoryRegistry) HasTask(name string) bool {
	mr.mu.RLock()
	defer mr.mu.RUnlock()

	_, exists := mr.tasks[name]
	return exists
}

// ListTasks lists all registered tasks
func (mr *MemoryRegistry) ListTasks() []string {
	mr.mu.RLock()
	defer mr.mu.RUnlock()

	tasks := make([]string, 0, len(mr.tasks))
	for name := range mr.tasks {
		tasks = append(tasks, name)
	}

	return tasks
}
